Skip to content

refactor: use destructured defaults over per-field ?? fallbacks - #248

Merged
jcarver989 merged 1 commit into
mainfrom
cb-bot/task-1785341815840
Jul 30, 2026
Merged

refactor: use destructured defaults over per-field ?? fallbacks#248
jcarver989 merged 1 commit into
mainfrom
cb-bot/task-1785341815840

Conversation

@contextbotai

@contextbotai contextbotai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What & why

The repository's AGENTS.md states a clear convention:

Destructured defaults over ?? fallbacks. When applying defaults to an options bag or similar object, use a single destructuring assignment with defaults instead of per-field ??. Write const { version = '0.0.0-development' } = input;, not const version = input.version ?? '0.0.0-development';. Keeps all the defaults for a function's input surface in one readable place.

I scanned every ?? usage across all packages and grouped them. Most are legitimate null-coalescing (Map.get fallbacks, optional-chaining results, array indexing, runtime object props) and are not violations. The violation class here is specifically per-field ?? defaulting on a function's options/deps bag. I fixed every instance:

  • packages/annotation/src/useSubmitOnCmdEnter.test.tsbuildKeyEvent applied init.metaKey ?? false, init.ctrlKey ?? false, init.preventDefault ?? (() => {}). Now destructures init with defaults in one place.
  • packages/cli/src/testHelpers/annotationFakes.tscreateAnnotationDependencies used options.submission ?? annotationSubmission.build() and options.result ?? Promise.resolve(submission). Now const { submission = annotationSubmission.build(), result = Promise.resolve(submission) } = options;.
  • packages/cli/src/updater/UpdaterImpl.tscheckForUpdate already destructured this.deps and options, but reached back through this.deps.ttl ?? Temporal.Duration.from(...) on a separate line. Folded ttl into the existing this.deps destructure with its default.

No runtime behavior changes — these are pure structural refactors. In annotationFakes.ts, moving result's default into the destructure evaluates Promise.resolve(submission) eagerly instead of inside the startReviewServer closure; since submission is already resolved at that point, the resulting settled promise is equivalent.

Verification

  • tsc typecheck: pass for @contextbridge/cli and @contextbridge/annotation.
  • prettier --check: pass on all three files.
  • eslint --max-warnings 0: pass on all three files.
  • bun test for UpdaterImpl.test.ts, plan.test.ts, open.test.ts (which exercise createAnnotationDependencies and UpdaterImpl): 57 pass, 0 fail.
  • The annotation package uses vitest browser mode, which cannot launch in this sandbox (Chromium/Playwright not installed — browserType.launch: Executable doesn't exist). This is a pre-existing environment limitation unrelated to the change; the package typechecks cleanly and the edit is a behavior-identical test-helper refactor.

Deliberately not changed (edge case)

packages/context/src/frontend.ts has const logger = loggerOverride ?? createLogger({ transmit: telemetry.pinoTransmit });. This is not a violation to fix: the input is already destructured (logger: loggerOverride), and the default cannot be inlined into the destructure because it depends on telemetry, which is computed later in the function body. Inlining it would force eager logger creation and change behavior.

Other violation classes observed (for future runs)

  • Hand-rolled createDeferred in a test filepackages/instrumentation/src/node/harnessDiscovery.test.ts defines a local createDeferred with a new Promise wrapper, which the testing-patterns rule explicitly prohibits (should import from @contextbridge/shared/testHelpers). Single instance; left for a focused follow-up.
  • toMatchObject for structured payloads — several test files use runs of field-by-field expect(obj.a).toBe(...) where one toMatchObject would fit. Fuzzy (the rule allows separate assertions for orthogonal behavior / specialized matchers), so risky to bulk-apply mechanically.
  • Bun-native file I/O — some production modules use readFileSync/writeFileSync/readdirSync where Bun.file/Bun.write/Bun.Glob are preferred, but the rule explicitly says these are "not banned outright," so it's a soft convention.

Bring options-bag default handling into compliance with the AGENTS.md
convention 'Destructured defaults over ?? fallbacks': apply defaults to
a function's input surface via a single destructuring assignment instead
of per-field `??`.

- annotation/useSubmitOnCmdEnter.test.ts: buildKeyEvent destructures init
- cli/testHelpers/annotationFakes.ts: createAnnotationDependencies
  destructures { submission, result } with defaults
- cli/updater/UpdaterImpl.ts: fold ttl default into the existing
  this.deps destructure

No behavior change.
@jcarver989
jcarver989 merged commit 044164d into main Jul 30, 2026
11 checks passed
@jcarver989
jcarver989 deleted the cb-bot/task-1785341815840 branch July 30, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant